import { AnimationMixer3D, Clock, Color, Node3D } from 'feng3d-three';
import { DRACOLoader3D } from '../../extension/loaders/DRACOLoader3D';
import { GLTFLoader3D } from '../../extension/loaders/GLTFLoader3D';

import '../../extension/controls/OrbitControls3D';
import '../../extension/environments/RoomEnvironment3D';

const gltfUrl = '../../models/gltf/LittlestTokyo.glb';
const decoderPath = '../../libs/draco/gltf/';

const root = new Node3D();

let mixer: AnimationMixer3D;

const clock = new Clock();
const container = document.getElementById('container');

const stats = root.addComponent('StatsComponent');
container.appendChild(stats.dom);

const renderer = root.addComponent('WebGLRenderer3D', {
    parameters: { antialias: true },
    pixelRatio: window.devicePixelRatio,
    size: { x: window.innerWidth, y: window.innerHeight },
});
renderer.outputEncoding = 'sRGBEncoding';
container.appendChild(renderer.domElement);

const pmremGenerator = new Node3D().addComponent('PMREMGenerator3D', { renderer });
const roomEnvironment = pmremGenerator.addComponent('RoomEnvironment3D');

const scene = root.addComponent('Scene3D');
scene.background = new Color(0xbfe3dd);
scene.environment = pmremGenerator.fromScene(roomEnvironment, 0.04).texture;

const camera = new Node3D().addComponent('PerspectiveCamera3D', { fov: 40, aspect: window.innerWidth / window.innerHeight, near: 1, far: 100 });
camera.entity.position.set(5, 2, 8);

const controls = new Node3D().addComponent('OrbitControls3D', { camera, domElement: renderer.domElement });
controls.target.set(0, 0.5, 0);
controls.update();
controls.enablePan = false;
controls.enableDamping = true;

const dracoLoader = new DRACOLoader3D();
dracoLoader.setDecoderPath(decoderPath);

const loader = new GLTFLoader3D();
loader.setDRACOLoader(dracoLoader);
loader.load(gltfUrl, function (gltf)
{
    const model = gltf.scene;
    model.position.set(1, 1, 0);
    model.scale.set(0.01, 0.01, 0.01);
    scene.entity.addChild(model);

    mixer = new AnimationMixer3D(model);
    mixer.clipAction(gltf.animations[0]).play();

    animate();
}, undefined, function (e)
{
    console.error(e);
});

window.onresize = function ()
{
    camera.aspect = window.innerWidth / window.innerHeight;

    renderer.setSize(window.innerWidth, window.innerHeight);
};

function animate()
{
    requestAnimationFrame(animate);

    const delta = clock.getDelta();

    mixer.update(delta);

    controls.update();

    stats.update();

    renderer.render(scene, camera);
}
